home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
CH_5.7
/
XSGLL
/
SGLL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
11KB
|
369 lines
/*
* sgll.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* SGLL
*
* construct segm adj list;
* version employing shortened segment structure; see also: lsgll.c
*
* ms, 11/90;
* ----------
* bug fixed in ACCEPT_LEVEL 1: ccurSegm->dij = -ccurSegm->dij:
* sign had been positive, leading to faulty segment ordering in
* SGL and subtle error in computed area and length!! ms, 2-26-91;
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include "lldef.h"
#include "xsgll.h"
#undef DEBUG
/*
* compare list entries (segments):
* key: distance parameter, dij
*
*/
int
cmpSegmdist (oldSegm, newSegm)
struct Segmtype *oldSegm, *newSegm;
{
return (SIGN (oldSegm->dij - newSegm->dij));
}
/*
* scan list, comparing perpendicular distance dij of newSegm <j>
* with that of those segments already in current segm adj list (SAL);
* add newSegm to list: if dij<0, addprev. otherwise add;
* employs matching function, here cmpSegmdist
* (see also: llsearch() in llist.c )
*/
Boolean
cmpdij (newSegm, sign_dij, sall)
struct Segmtype *newSegm;
int sign_dij;
struct linklist *sall;
{
Boolean MatchStatus = False;
if (sign_dij > 0) { /* scan bwd from tail until newdij <= existdij */
lltail (sall);
do {
if (((*sall->match) (sall->clp->item, newSegm)) <= 0)
MatchStatus = True;
} while ((MatchStatus != True) && (llprevious (sall) == True));
}
else { /* scan fwd from head until newdij > existdij */
llhead (sall);
do {
if (((*sall->match) (sall->clp->item, newSegm)) > 0)
MatchStatus = True;
} while ((MatchStatus != True) && (llnext (sall) == True));
}
return (MatchStatus);
}
/*
* to check value of inv overlap pki of segment <k> in SAL<j> with
* the reference segment <i>, fetch segm <k>
*/
struct Segmtype *
fetch_segm (csall, sgl_ind)
struct linklist *csall;
int sgl_ind;
{
struct Segmtype *cSegm;
Boolean MatchStatus = False;
llhead (csall); /* search SAL for segm <sgl_index> */
/* skip ref segm at top of list */
while ((llnext (csall) == True) && (MatchStatus != True)) {
cSegm = (struct Segmtype *) csall->clp->item;
if (cSegm->segm_ind == sgl_ind)
MatchStatus = True;
}
if (MatchStatus == True)
return (cSegm);
else
return ((struct Segmtype *) NULL);
}
/*
* scan SAL and check whether active segments remain;
* if so, return Active, otherwise set SalStat of the reference
* segment of the SAL under inspection to InActive and return InActive
*/
Boolean
check_sal_stat (ActiveSegm, list)
Boolean *ActiveSegm;
struct linklist *list;
{
struct Segmtype *cccSegm, *rrrefSegm;
Boolean SalStat = InActive;
llhead (list);
rrrefSegm = (struct Segmtype *) list->clp->item; /* ref segm at top */
do {
cccSegm = (struct Segmtype *) list->clp->item;
if (*(ActiveSegm + cccSegm->segm_ind) == Active)
SalStat = Active;
} while ((llnext (list) == True) && (SalStat == InActive));
rrrefSegm->SalStat = SalStat;
return (SalStat);
}
/*
* expand doubly linked list by adding a segment, maintaining
* segments in increasing order of dij
*/
void
llexpand (Segm, list)
struct Segmtype *Segm;
struct linklist *list;
{
int s_dij;
llsetmatch (cmpSegmdist, list);
switch (s_dij = SIGN (Segm->dij)) {
case -1:
llhead (list);
while (cmpdij (Segm, s_dij, list) != True);
lladdprev ((char *) Segm, list);
break;
case 1:
lltail (list);
while (cmpdij (Segm, s_dij, list) != True);
lladd ((char *) Segm, list);
break;
case 0:
printf ("\n...overlap ignored\n");
break;
default:
printf ("\n...unknown SIGN(dij)!\n");
break;
}
}
/*
* construct segment group list
* return number of SGLs containing more than the reference segment
*/
int
construct_sgll (segm, sall, sgll, n_segm, ovlp_thresh)
struct Segm *segm;
struct linklist *sall;
struct linklist *sgll;
int n_segm;
double ovlp_thresh;
{
int n_sgl;
struct linklist *csall, *ccsall, *cccsall; /* ptrs to current lists */
struct linklist *csgll;
Boolean *ActiveSegm;
struct Segmtype *refSegm, *curSegm;
struct Segmtype *rrefSegm, *ccurSegm, *cccurSegm;
double dij, dji, pij, pji;
double pki, pkj;
int i, ref_index;
int na_segm, naa_segm;
Boolean SalStat;
/*
* ActiveSegm is an array to globally track the status of segments
* as they are being assigned to SGLs; each segment mmay only be
* be assigned once;
* Active: segment unassigned
* InActive: segment assigned
*/
ActiveSegm = (Boolean *) calloc (n_segm, sizeof (Boolean));
for (i = 0; i < n_segm; i++)
*(ActiveSegm + i) = Active;
n_sgl = 0;
for (i = 0; i < n_segm; i++) {
csall = (sall + i);
llhead (csall); /* ref segm of SAL<i> stored at top */
refSegm = (struct Segmtype *) csall->clp->item;
ref_index = i;
na_segm = 0;
if (refSegm->SalStat == Active) { /* SAL active? */
csgll = (sgll + i); /* set current SGL */
llinit ((char *) refSegm, csgll); /* init. SGL<i> with ref segm */
ActiveSegm[refSegm->segm_ind] = InActive;
printf ("\n...SGL<%d> initialized\n", i);
/*
* scan SAL<i>, the SAL of the reference segment:
* inspect all active segments <j != i> in the SAL; if pji passes
* OVLP_THRESH, add <j> to SGL<i> in the order of increasing dij;
* when reaching the first segm in SAL<i> for which pji<OVLP_THRESH,
* stop scanning (pji for all followin segments will be smaller!!) and
* set na_segm != 0 to signal end of scan;
* in SGL<i> segments with dij<0 will precede the reference element,
* those with dij>0 will follow it
*/
while ((llnext (csall) == True) && (na_segm == 0)) {
curSegm = (struct Segmtype *) csall->clp->item;
if (ActiveSegm[curSegm->segm_ind] == Active) {
if (curSegm->pji > ovlp_thresh) {
llexpand (curSegm, csgll);
ActiveSegm[curSegm->segm_ind] = InActive;
}
else
na_segm++; /* segm remains active */
}
} /* reached end of cur SAL */
if (csgll->listlength > 1)
n_sgl++; /* count SGLs with more than 1 segm */
if (na_segm == 0) /* no active segm remaining in SAL<i> */
refSegm->SalStat = InActive;
/*
* expand SGL<i> if ACCEPT_LEVEL > 0 is indicated:
* scan SGL<i>, the segm group list just constructed (segments added to
* SGL<i> at that level are considered to satisfy ACCEPT_LEVEL 0);
* inspect all active SALs of segments <j> present in SGL<i> (excluding
* SAL<i> which has just been examined); in each SAL<j>, inspect active
* elements <k> and compare inverse overlap with OVLP_THRESH:
* if pki>OVLP_THRESH: add <k> to SGL<i>
* if ACCEPT_LEVEL == 2:
* if pji>OVLP_THRESH: add <k> to SGL<i>
*/
if (ACCEPT_LEVEL > 0) {
llhead (csgll); /* scan SGL<i>, inspecting SAL<j> */
do {
curSegm = (struct Segmtype *) csgll->clp->item;
if (curSegm->segm_ind != ref_index) { /* skip SAL<i> */
ccsall = &sall[curSegm->segm_ind]; /* fetch SAL<j> */
llhead (ccsall); /* ref segm stored at top of SAL */
rrefSegm = (struct Segmtype *) ccsall->clp->item;
naa_segm = 0;
if (rrefSegm->SalStat == Active) { /*scan SAL if actv */
while (llnext (ccsall) == True) {
ccurSegm = (struct Segmtype *) ccsall->clp->item;
if (ActiveSegm[ccurSegm->segm_ind] == Active) {
cccsall = &sall[ccurSegm->segm_ind]; /* SAL<k> */
cccurSegm = fetch_segm (cccsall, ref_index);
if (cccurSegm != (struct Segmtype *) NULL)
pki = (double) cccurSegm->pij;
else {
pki = -1.0;
}
/* test inverse overlap */
/* add segm to SGL if indicated */
/* ACCEPT_LEVEL 1 */
if (pki > ovlp_thresh) {
ccurSegm->dij = -cccurSegm->dij;
ccurSegm->pij = cccurSegm->pji;
ccurSegm->pji = (float) pki;
ccurSegm->sgl_level = 1;
llexpand (ccurSegm, csgll);
ActiveSegm[ccurSegm->segm_ind] = InActive;
llhead (csgll); /* scan SGL from top */
}
else if (ACCEPT_LEVEL > 1) {
cccurSegm = fetch_segm (cccsall, curSegm->segm_ind);
if (cccurSegm != (struct Segmtype *) NULL) {
pkj = (double) cccurSegm->pij;
}
else {
pkj = -1.0;
}
/* must reevaluate dij, pij, pji */
/* with respect to ref segment <i>!! */
/* ACCEPT_LEVEL 2 */
if (pkj > ovlp_thresh) {
prlpar ((segm + ccurSegm->segm_ind)->ptO,
(segm + ccurSegm->segm_ind)->ptF,
(segm + refSegm->segm_ind)->ptO,
(segm + refSegm->segm_ind)->ptF,
&dij, &dji, &pij, &pji);
#ifdef DEBUG
printf ("\n...returned from prlpar():\n");
printf (" overlap(%d,%d)=%.2lf\n",
ccurSegm->segm_ind,
refSegm->segm_ind, pij);
printf (" overlap(%d,%d)=%.2lf\n",
refSegm->segm_ind,
ccurSegm->segm_ind, pji);
printf (" perp.dist(%d,%d)=%.2lf\n",
ccurSegm->segm_ind,
refSegm->segm_ind, dji);
#endif
ccurSegm->dij = (float) dji;
ccurSegm->pij = (float) pij;
ccurSegm->pji = (float) pji;
ccurSegm->sgl_level = 2;
llexpand (ccurSegm, csgll);
ActiveSegm[ccurSegm->segm_ind] = InActive;
/* pro-active check of SAL status: */
/* scan SAL<k> to see if actv segm remain */
/* if not, mark SAL<k> InActive */
SalStat = check_sal_stat (ActiveSegm, cccsall);
llhead (csgll); /* scan SGL from top */
}
}
else
naa_segm++; /* segm remains active */
}
} /* reached end of cur SAL */
if (naa_segm == 0) /* no actv segm remain in SAL */
rrefSegm->SalStat = InActive;
}
}
} while (llnext (csgll) == True); /* end of SGL<i> */
}
}
}
free (ActiveSegm);
return (n_sgl);
}